home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue48 / Alfresco / AACRC.pas next >
Encoding:
Pascal/Delphi Source File  |  1999-06-20  |  15.9 KB  |  579 lines

  1. {*********************************************************}
  2. {* AACRC                                                 *}
  3. {* Copyright (c) Julian M Bucknall 1998-1999             *}
  4. {* All rights reserved.                                  *}
  5. {*********************************************************}
  6. {* Algorithms Alfresco CRC unit                          *}
  7. {*********************************************************}
  8.  
  9. {Note: this unit is released as freeware. In other words, you are free
  10.        to use this unit in your own applications, however I retain all
  11.        copyright to the code. JMB}
  12.  
  13. unit AACRC;
  14.  
  15. {$I AADefine.INC}
  16.  
  17. interface
  18.  
  19. uses
  20.   SysUtils;
  21.  
  22. const
  23.   {magic polynomials for standard CRC implementations}
  24.   {..16-bit}
  25.   PolyCRCCCITT = $1021;
  26.   PolyXMODEMCRC = $1021;
  27.   PolyCRC16 = $8005;
  28.   {..32-bit}
  29.   PolyCRC32 = $04C11DB7;
  30.   PolyAAL5 = $04C11DB7;
  31.  
  32. type
  33.   TaaCRC16 = word;
  34.   {$IFDEF Delphi4Plus}
  35.   TaaCRC32 = longword;
  36.   {$ELSE}
  37.   TaaCRC32 = longint;
  38.   {$ENDIF}
  39.  
  40.   Paa16BitCRCTable = ^Taa16BitCRCTable;
  41.   Taa16BitCRCTable = array [0..255] of TaaCRC16;
  42.  
  43.   Paa32BitCRCTable = ^Taa32BitCRCTable;
  44.   Taa32BitCRCTable = array [0..255] of TaaCRC32;
  45.  
  46. type
  47.   TaaCRC16Calculator = class
  48.     private
  49.       ccInitValue   : TaaCRC16;
  50.       ccMagicPoly   : TaaCRC16;
  51.       ccNotResult   : boolean;
  52.       ccReverseBits : boolean;
  53.       ccTable       : Paa16BitCRCTable;
  54.     protected
  55.       procedure ccCreateTable;
  56.     public
  57.       constructor Create(aMagicPoly   : TaaCRC16;
  58.                          aReverseBits : boolean;
  59.                          aInitValue   : TaaCRC16;
  60.                          aNotResult   : boolean);
  61.       destructor Destroy; override;
  62.  
  63.       function GetCRC(var aBuffer; aBufLen : integer) : TaaCRC16;
  64.       function GetCRCStd(var aBuffer; aBufLen : integer) : TaaCRC16;
  65.  
  66.       function UpdateCRC(aValue : byte; aCRC : TaaCRC16) : TaaCRC16;
  67.  
  68.       procedure SaveToIncFile(const aIncFileName : string);
  69.   end;
  70.  
  71.   TaaCRC32Calculator = class
  72.     private
  73.       ccInitValue   : TaaCRC32;
  74.       ccMagicPoly   : TaaCRC32;
  75.       ccNotResult   : boolean;
  76.       ccReverseBits : boolean;
  77.       ccTable       : Paa32BitCRCTable;
  78.     protected
  79.       procedure ccCreateTable;
  80.     public
  81.       constructor Create(aMagicPoly   : TaaCRC32;
  82.                          aReverseBits : boolean;
  83.                          aInitValue   : TaaCRC32;
  84.                          aNotResult   : boolean);
  85.       destructor Destroy; override;
  86.  
  87.       function GetCRC(var aBuffer; aBufLen : integer) : TaaCRC32;
  88.       function GetCRCStd(var aBuffer; aBufLen : integer) : TaaCRC32;
  89.  
  90.       function UpdateCRC(aValue : byte; aCRC : TaaCRC32) : TaaCRC32;
  91.  
  92.       procedure SaveToIncFile(const aIncFileName : string);
  93.   end;
  94.  
  95. {routines used in article exposition}
  96. function AAGet16BitCRCStd(var aBuffer; aBufLen    : integer;
  97.                               aMagicPoly : TaaCRC16) : TaaCRC16;
  98.  
  99. procedure AACalc16BitCRCTable(var aTable     : Taa16BitCRCTable;
  100.                                   aMagicPoly : TaaCRC16);
  101.  
  102. function AAGet16BitCRCTbl(var aBuffer; aBufLen : integer;
  103.                         const aTable  : Taa16BitCRCTable) : TaaCRC16;
  104.  
  105. implementation
  106.  
  107. {===Helper routines==================================================}
  108. function IntToHex(aValue : longint; aCount : integer) : string;
  109.   {-return the hex string with aCount digits for aValue}
  110. var
  111.   Digit : integer;
  112.   Mask  : longint;
  113.   i     : integer;
  114. begin
  115.   Result := '';
  116.   Mask := longint($F) shl (pred(aCount) * 4);
  117.   for i := pred(aCount) downto 0 do begin
  118.     Digit := (aValue and Mask) shr (i * 4);
  119.     if (Digit <= 9) then
  120.       Result := Result + char(ord('0') + Digit)
  121.     else
  122.       Result := Result + char(ord('a') + Digit - 10);
  123.     Mask := Mask shr 4;
  124.   end;
  125. end;
  126. {--------}
  127. function ReverseBits(aValue : longint; aBits : integer) : longint;
  128. var
  129.   i : integer;
  130. begin
  131.   Result := 0;
  132.   for i := 0 to pred(aBits) do begin
  133.     if Odd(aValue) then
  134.       Result := (Result shl 1) or 1
  135.     else
  136.       Result := (Result shl 1);
  137.     aValue := aValue shr 1;
  138.   end;
  139. end;
  140. {--------}
  141. procedure WriteHeader(const aIncFileName : string;
  142.                       var F : text);
  143. var
  144.   FileName : string;
  145. begin
  146.   FileName := ExtractFileName(aIncFileName);
  147.   writeln(F, '{*********************************************************}');
  148.   writeln(F, '{* ', FileName, ' ':54-length(FileName), '*}');
  149.   writeln(F, '{* Copyright (c) Julian M Bucknall 1998-1999             *}');
  150.   writeln(F, '{* All rights reserved.                                  *}');
  151.   writeln(F, '{*********************************************************}');
  152.   writeln(F, '{* Algorithms Alfresco auto-generated CRC table          *}');
  153.   writeln(F, '{*********************************************************}');
  154.   writeln(F);
  155. end;
  156.  
  157. {====================================================================}
  158.  
  159.  
  160. {===TaaCRC16Calculator===============================================}
  161. constructor TaaCRC16Calculator.Create(aMagicPoly   : TaaCRC16;
  162.                                       aReverseBits : boolean;
  163.                                       aInitValue   : TaaCRC16;
  164.                                       aNotResult   : boolean);
  165. begin
  166.   inherited Create;
  167.   ccMagicPoly := aMagicPoly;
  168.   ccReverseBits := aReverseBits;
  169.   ccInitValue := aInitValue;
  170.   ccNotResult := aNotResult;
  171. end;
  172. {--------}
  173. destructor TaaCRC16Calculator.Destroy;
  174. begin
  175.   if (ccTable <> nil) then
  176.     Dispose(ccTable);
  177.   inherited Destroy;
  178. end;
  179. {--------}
  180. procedure TaaCRC16Calculator.ccCreateTable;
  181. const
  182.   TopmostBitMask = $8000;
  183. var
  184.   i   : integer;
  185.   Reg : TaaCRC16;
  186.   bit : integer;
  187. begin
  188.   New(ccTable);
  189.   for i := 0 to 255 do begin
  190.     if ccReverseBits then
  191.       Reg := ReverseBits(i, 16)
  192.     else
  193.       Reg := i shl 8;
  194.     for bit := 0 to 7 do begin
  195.       if ((Reg and TopmostBitMask) <> 0) then
  196.         Reg := (Reg shl 1) xor ccMagicPoly
  197.       else
  198.         Reg := (Reg shl 1);
  199.     end;
  200.     if ccReverseBits then
  201.       ccTable^[i] := ReverseBits(Reg, 16)
  202.     else
  203.       ccTable^[i] := Reg;
  204.   end;
  205. end;
  206. {--------}
  207. function TaaCRC16Calculator.GetCRC(var aBuffer; aBufLen : integer) : TaaCRC16;
  208. var
  209.   i   : integer;
  210.   Reg : TaaCRC32;
  211.   Buf : TByteArray absolute aBuffer;
  212. begin
  213.   {if the CRC table hasn't yet been calculated, allocate it and do so}
  214.   if (ccTable = nil) then
  215.     ccCreateTable;
  216.   {initialise the register}
  217.   Reg := ccInitValue;
  218.   {calculate the CRC}
  219.   if ccReverseBits then
  220.     for i := 0 to pred(aBufLen) do
  221.       Reg := ccTable^[byte(Reg) xor Buf[i]] xor (Reg shr 8)
  222.   else
  223.     for i := 0 to pred(aBufLen) do
  224.       Reg := ccTable^[byte(Reg shr 8) xor Buf[i]] xor (Reg shl 8);
  225.   {if required, not the result}
  226.   if ccNotResult then
  227.     Reg := not Reg;
  228.   {return the register}
  229.   Result := Reg;
  230. end;
  231. {--------}
  232. function TaaCRC16Calculator.GetCRCStd(var aBuffer; aBufLen : integer) : TaaCRC16;
  233. var
  234.   i   : integer;
  235.   Buf : TByteArray absolute aBuffer;
  236.   Reg : TaaCRC16;
  237.   B   : byte;
  238.   bit : integer;
  239.   MagicPoly : TaaCRC16;
  240. begin
  241.   {initialise the register}
  242.   Reg := ccInitValue;
  243.  
  244.   {split the flow: first the case for feeding in bytes the least
  245.    significant bit first}
  246.   if ccReverseBits then begin
  247.     {reverse the magic polynomial}
  248.     MagicPoly := ReverseBits(ccMagicPoly, 16);
  249.     {do for all bytes in the buffer...}
  250.     for i := 0 to pred(aBufLen) do begin
  251.       B := Buf[i];
  252.       for bit := 0 to 7 do begin
  253.         if ((Reg and 1) xor (B and 1)) <> 0 then
  254.           Reg := (Reg shr 1) xor MagicPoly
  255.         else
  256.           Reg := (Reg shr 1);
  257.         B := B shr 1;
  258.       end;
  259.     end;
  260.   end
  261.  
  262.   {now the case for feeding in bytes the most significant bit first}
  263.   else begin
  264.     {do for all bytes in the buffer...}
  265.     for i := 0 to pred(aBufLen) do begin
  266.       B := Buf[i];
  267.       for bit := 0 to 7 do begin
  268.         if ((B shr 7) xor ((Reg and $8000) shr 15)) <> 0 then
  269.           Reg := (Reg shl 1) xor ccMagicPoly
  270.         else
  271.           Reg := (Reg shl 1);
  272.         B := B shl 1;
  273.       end;
  274.     end;
  275.   end;
  276.  
  277.   {if required, not the result}
  278.   if ccNotResult then
  279.     Reg := not Reg;
  280.   {return the register}
  281.   Result := Reg;
  282. end;
  283. {--------}
  284. procedure TaaCRC16Calculator.SaveToIncFile(const aIncFileName : string);
  285. var
  286.   F : text;
  287.   i : integer;
  288.   j : integer;
  289. begin
  290.   {if the CRC table hasn't yet been calculated, allocate it and do so}
  291.   if (ccTable = nil) then
  292.     ccCreateTable;
  293.   {create the file anew}
  294.   System.Assign(F, aIncFileName);
  295.   System.Rewrite(F);
  296.   try
  297.     WriteHeader(aIncFileName, F);
  298.     writeln(F, 'const');
  299.     writeln(F, '  AACRCTable16 : array [0..255] of TaaCRC16 = (');
  300.     j := 0;
  301.     for i := 0 to 255 do begin
  302.       if (j = 0) then
  303.         write(F, '     ');
  304.       write(F, '$', IntToHex(ccTable^[i], 4));
  305.       if i = 255 then
  306.         write(F, ');')
  307.       else
  308.         write(F, ', ');
  309.       inc(j);
  310.       if (j = 8) then begin
  311.         writeln(F);
  312.         j := 0;
  313.       end;
  314.     end;
  315.     writeln(F);
  316.   finally
  317.     System.Close(F);
  318.   end;
  319. end;
  320. {--------}
  321. function TaaCRC16Calculator.UpdateCRC(aValue : byte; aCRC : TaaCRC16) : TaaCRC16;
  322. begin
  323.   if ccReverseBits then
  324.     Result := ccTable^[byte(aCRC) xor aValue] xor (aCRC shr 8)
  325.   else
  326.     Result := ccTable^[byte(aCRC shr 8) xor aValue] xor (aCRC shl 8);
  327. end;
  328. {====================================================================}
  329.  
  330.  
  331. {===TaaCRC32Calculator===============================================}
  332. constructor TaaCRC32Calculator.Create(aMagicPoly   : TaaCRC32;
  333.                                       aReverseBits : boolean;
  334.                                       aInitValue   : TaaCRC32;
  335.                                       aNotResult   : boolean);
  336. begin
  337.   inherited Create;
  338.   ccMagicPoly := aMagicPoly;
  339.   ccReverseBits := aReverseBits;
  340.   ccInitValue := aInitValue;
  341.   ccNotResult := aNotResult;
  342. end;
  343. {--------}
  344. destructor TaaCRC32Calculator.Destroy;
  345. begin
  346.   if (ccTable <> nil) then
  347.     Dispose(ccTable);
  348.   inherited Destroy;
  349. end;
  350. {--------}
  351. procedure TaaCRC32Calculator.ccCreateTable;
  352. const
  353.   TopmostBitMask = $80000000;
  354. var
  355.   i   : integer;
  356.   Reg : TaaCRC32;
  357.   bit : integer;
  358. begin
  359.   New(ccTable);
  360.   for i := 0 to 255 do begin
  361.     if ccReverseBits then
  362.       Reg := ReverseBits(i, 32)
  363.     else
  364.       Reg := TaaCRC32(i) shl 24;
  365.     for bit := 0 to 7 do begin
  366.       if ((Reg and TopmostBitMask) <> 0) then
  367.         Reg := (Reg shl 1) xor ccMagicPoly
  368.       else
  369.         Reg := (Reg shl 1);
  370.     end;
  371.     if ccReverseBits then
  372.       ccTable^[i] := ReverseBits(Reg, 32)
  373.     else
  374.       ccTable^[i] := Reg;
  375.   end;
  376. end;
  377. {--------}
  378. function TaaCRC32Calculator.GetCRC(var aBuffer; aBufLen : integer) : TaaCRC32;
  379. var
  380.   i   : integer;
  381.   Reg : TaaCRC32;
  382.   Buf : TByteArray absolute aBuffer;
  383. begin
  384.   {if the CRC table hasn't yet been calculated, allocate it and do so}
  385.   if (ccTable = nil) then 
  386.     ccCreateTable;
  387.   {initialise the register}
  388.   Reg := ccInitValue;
  389.   {calculate the CRC}
  390.   if ccReverseBits then
  391.     for i := 0 to pred(aBufLen) do
  392.       Reg := ccTable^[byte(Reg) xor Buf[i]] xor (Reg shr 8)
  393.   else
  394.     for i := 0 to pred(aBufLen) do
  395.       Reg := ccTable^[byte(Reg shr 24) xor Buf[i]] xor (Reg shl 8);
  396.   {if required, not the result}
  397.   if ccNotResult then
  398.     Reg := not Reg;
  399.   {return the register}
  400.   Result := Reg;
  401. end;
  402. {--------}
  403. function TaaCRC32Calculator.GetCRCStd(var aBuffer; aBufLen : integer) : TaaCRC32;
  404. var
  405.   i   : integer;
  406.   Buf : TByteArray absolute aBuffer;
  407.   Reg : TaaCRC32;
  408.   bit : integer;
  409.   B   : byte;
  410.   MagicPoly : TaaCRC32;
  411. begin
  412.   {initialise the register}
  413.   Reg := ccInitValue;
  414.  
  415.   {split the flow: first the case for feeding in bytes the least
  416.    significant bit first}
  417.   if ccReverseBits then begin
  418.     {reverse the magic polynomial}
  419.     MagicPoly := ReverseBits(ccMagicPoly, 32);
  420.     {do for all bytes in the buffer...}
  421.     for i := 0 to pred(aBufLen) do begin
  422.       B := Buf[i];
  423.       for bit := 0 to 7 do begin
  424.         if ((Reg and 1) xor (B and 1)) <> 0 then
  425.           Reg := (Reg shr 1) xor MagicPoly
  426.         else
  427.           Reg := (Reg shr 1);
  428.         B := B shr 1;
  429.       end;
  430.     end;
  431.   end
  432.  
  433.   {now the case for feeding in bytes the most significant bit first}
  434.   else begin
  435.     {do for all bytes in the buffer...}
  436.     for i := 0 to pred(aBufLen) do begin
  437.       B := Buf[i];
  438.       for bit := 0 to 7 do begin
  439.         if ((B shr 7) xor (Reg shr 31)) <> 0 then
  440.           Reg := (Reg shl 1) xor ccMagicPoly
  441.         else
  442.           Reg := (Reg shl 1);
  443.         B := B shl 1;
  444.       end;
  445.     end;
  446.   end;
  447.  
  448.   {if required, not the result}
  449.   if ccNotResult then
  450.     Reg := not Reg;
  451.   {return the register}
  452.   Result := Reg;
  453. end;
  454. {--------}
  455. procedure TaaCRC32Calculator.SaveToIncFile(const aIncFileName : string);
  456. var
  457.   F : text;
  458.   i : integer;
  459.   j : integer;
  460. begin
  461.   {if the CRC table hasn't yet been calculated, allocate it and do so}
  462.   if (ccTable = nil) then
  463.     ccCreateTable;
  464.   {create the file anew}
  465.   System.Assign(F, aIncFileName);
  466.   System.Rewrite(F);
  467.   try
  468.     WriteHeader(aIncFileName, F);
  469.     writeln(F, 'const');
  470.     writeln(F, '  AACRCTable32 : array [0..255] of TaaCRC32 = (');
  471.     j := 0;
  472.     for i := 0 to 255 do begin
  473.       if (j = 0) then
  474.         write(F, '     ');
  475.       write(F, '$', IntToHex(ccTable^[i], 8));
  476.       if i = 255 then
  477.         write(F, ');')
  478.       else
  479.         write(F, ', ');
  480.       inc(j);
  481.       if (j = 6) then begin
  482.         writeln(F);
  483.         j := 0;
  484.       end;
  485.     end;
  486.     writeln(F);
  487.   finally
  488.     System.Close(F);
  489.   end;
  490. end;
  491. {--------}
  492. function TaaCRC32Calculator.UpdateCRC(aValue : byte; aCRC : TaaCRC32) : TaaCRC32;
  493. begin
  494.   if ccReverseBits then
  495.     Result := ccTable^[byte(aCRC) xor aValue] xor (aCRC shr 8)
  496.   else
  497.     Result := ccTable^[byte(aCRC shr 24) xor aValue] xor (aCRC shl 8);
  498. end;
  499. {====================================================================}
  500.  
  501.  
  502. {===Standard CRC routines============================================}
  503. function AAGet16BitCRCStd(var aBuffer; aBufLen    : integer;
  504.                               aMagicPoly : TaaCRC16) : TaaCRC16;
  505. const
  506.   TopmostBitMask = $8000;
  507. var
  508.   i   : integer;
  509.   Buf : TByteArray absolute aBuffer;
  510.   Reg : TaaCRC16;
  511.   B   : byte;
  512.   bit : integer;
  513. begin
  514.   {initialise the register}
  515.   Reg := 0;
  516.  
  517.   {do for all bytes in the buffer...}
  518.   for i := 0 to pred(aBufLen) do begin
  519.     B := Buf[i];
  520.     {do for all bits in the current byte}
  521.     for bit := 0 to 7 do begin
  522.       {if the high bit of the register is 1, shift the register left
  523.        by one, xor in the next bit from the byte, and xor the magic
  524.        polynomial}
  525.       if ((Reg and TopmostBitMask) <> 0) then
  526.         Reg := (Reg shl 1) xor (B shr 7) xor aMagicPoly
  527.       {otherwise the high bit of the register is 0, shift the register
  528.        left by one, xor in the next bit from the byte}
  529.       else
  530.         Reg := (Reg shl 1) xor (B shr 7);
  531.       B := B shl 1;
  532.     end;
  533.   end;
  534.  
  535.   {return the register}
  536.   Result := Reg;
  537. end;
  538. {--------}
  539. procedure AACalc16BitCRCTable(var aTable     : Taa16BitCRCTable;
  540.                                   aMagicPoly : TaaCRC16);
  541. const
  542.   TopmostBitMask = $8000;
  543. var
  544.   i   : integer;
  545.   Reg : TaaCRC16;
  546.   bit : integer;
  547. begin
  548.   for i := 0 to 255 do begin
  549.     Reg := i shl 8;
  550.     for bit := 0 to 7 do begin
  551.       if ((Reg and TopmostBitMask) <> 0) then
  552.         Reg := (Reg shl 1) xor aMagicPoly
  553.       else
  554.         Reg := (Reg shl 1);
  555.     end;
  556.     aTable[i] := Reg;
  557.   end;
  558. end;
  559. {--------}
  560. function AAGet16BitCRCTbl(var aBuffer;
  561.                               aBufLen    : integer;
  562.                         const aTable     : Taa16BitCRCTable) : TaaCRC16;
  563. var
  564.   i   : integer;
  565.   Buf : TByteArray absolute aBuffer;
  566.   Reg : TaaCRC16;
  567. begin
  568.   {initialise the register}
  569.   Reg := 0;
  570.   {calculate the CRC}
  571.   for i := 0 to pred(aBufLen) do
  572.     Reg := aTable[byte(Reg shr 8) xor Buf[i]] xor (Reg shl 8);
  573.   {return the register}
  574.   Result := Reg;
  575. end;
  576. {====================================================================}
  577.  
  578. end.
  579.